package com.tuzhi.auth.sys.web.controller;


import com.tuzhi.auth.sys.config.ConstantConfig;
import com.tuzhi.auth.sys.dto.SysMenuTreeDto;
import com.tuzhi.auth.sys.jpa.entity.SysUserEntity;
import com.tuzhi.auth.sys.jpa.entity.SystemLogEntity;
import com.tuzhi.auth.sys.scurity.AuthService;
import com.tuzhi.auth.sys.scurity.AuthTokenService;
import com.tuzhi.auth.sys.service.SysDictionaryService;
import com.tuzhi.auth.sys.service.SysUserService;
import com.tuzhi.auth.sys.service.SystemLogService;
import com.tuzhi.auth.sys.web.controller.vo.LoginVO;
import com.tuzhi.base.web.annotation.GlobalApiResultJson;
import com.tuzhi.base.web.helper.AjaxResultHelper;
import com.tuzhi.base.web.util.ServletUtil;
import com.tuzhi.base.web.vo.AjaxResultVO;
import com.tuzhi.common.constants.AppConstant;
import com.tuzhi.common.domain.LoginUserBO;
import com.tuzhi.common.domain.ResultBO;
import com.tuzhi.common.exception.BusinessException;
import com.tuzhi.util.StringTzUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

@Slf4j
@RestController
@Api(tags = "系统登录，退出登录")
public class LoginController {
  /*  @Autowired
    UserService userService;*/

    @Autowired
    SysUserService sysUserService;

    @Autowired
    SysDictionaryService sysDictionaryService;

    @Autowired
    AuthService authService;

    @Autowired
    SystemLogService systemLogService;

    @Autowired
    AuthTokenService authTokenService;

    @Value("${login.appPwd:test}")
    private String appPwd;


    /* @ApiOperation(value = "登录", notes = "通过用户名密码登录，获取token,调用方必须把最新获取的token替换上一次的token")
    @PostMapping("/login")
    @Deprecated
   public AjaxResultVO login(@ApiParam("登录信息") @RequestBody LoginVO loginVO) {
        try {
            if (loginVO.getLogintype() == 1) {
                loginVO.setMobile(loginVO.getUsername());
            }
            *//*LoginUserBO loginUserBO = authTokenService.login(loginVO.getUsername(), loginVO.getPassword(),
                    "codeKey", "code", loginVO.getLogintype(), loginVO.getMobile());*//*
            LoginUserBO loginUserBO = authTokenService.login(loginVO.getUsername(), loginVO.getPassword()
                    , loginVO.getLogintype(), loginVO.getMobile());
            loginVO.setUsername(loginUserBO.getUserName());
            AjaxResultVO ajax = AjaxResultHelper.success();
            ajax.setData(loginUserBO.getToken());

            //获取日志内容模板
            String logFormat = sysDictionaryService.getUniqueValue(ConstantConfig.LOGIN_LOG_DIC_NAME);
            String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            logFormat = logFormat = logFormat.replaceAll("%userName%", loginVO.getUsername()).replaceAll("%loginTime%", date);
            // 组装记录登录日志
            SystemLogEntity systemLogEntity = new SystemLogEntity()
                    .setLogContent(logFormat)
                    .setLogType(SystemLogEntity.LogType.LOGIN_LOGOUT_LOG.getDescription())
                    .setModule(SystemLogEntity.Module.AUTH)
                    .setOperationTime(new Date())
                    .setOperator("system")
                    .setLogCategory(SystemLogEntity.LogType.LOGIN_LOGOUT_LOG.getCategory());
            systemLogService.save(systemLogEntity);
            return ajax;
        } catch (BusinessException ex) {
            AjaxResultVO ajax = AjaxResultHelper.error();
            ajax.setCode(ex.getCode());
            ajax.setMsg(ex.getMessage());
            return ajax;
        } catch (Exception ex) {
            AjaxResultVO ajax = AjaxResultHelper.error();
            ajax.setCode("-1");
            ajax.setMsg(ex.getMessage());
            return ajax;
        }
    }*/

    @ApiOperation(value = "退出登录", notes = "清除服务端保存的token信息,必须是带上当前用户的token信息，才能退出成功")
    @GetMapping("logout")
    public AjaxResultVO logout() {
        //获取日志内容模板
//        LoginUserBO curLoginUser = UserContext.getUserInfo(true);
//        String logFormat = sysDictionaryService.getUniqueValue(ConstantConfig.LOGOUT_LOG_DIC_NAME);
//        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
//        logFormat = logFormat.replaceAll("%userName%", curLoginUser.getUserName()).replaceAll("%loginTime%", date);
//        // 组装记录登录日志
//        SystemLogEntity systemLogEntity = new SystemLogEntity()
//                .setLogContent(logFormat)
//                .setLogType(SystemLogEntity.LogType.LOGIN_LOGOUT_LOG.getDescription())
//                .setModule(SystemLogEntity.Module.AUTH)
//                .setOperationTime(new Date())
//                .setOperator("system")
//                .setLogCategory(SystemLogEntity.LogType.LOGIN_LOGOUT_LOG.getCategory());
//        systemLogService.save(systemLogEntity);
        AjaxResultVO ajax = AjaxResultHelper.success();
        //userService.loginOut();
        authTokenService.loginOut();
        log.warn("退出成功");
        return ajax;
    }

    @ApiOperation(value = "登录,并返回当前用户的角色数组", notes = "通过用户名密码登录，获取token,调用方必须把最新获取的token替换上一次的token")
    @PostMapping("/loginAndGetRole")
    public AjaxResultVO loginAndGetRole(@ApiParam("登录信息") @RequestBody LoginVO loginVO) {
        try {


            if (loginVO == null) {
                throw new BusinessException("登录参数不能为空");
            }
            if (loginVO.getLogintype() == 0) {
                if (StringTzUtil.isBlankNull(loginVO.getUsername())) {
                    throw new BusinessException("登录帐号不能为空");
                }
                if (StringTzUtil.isBlankNull(loginVO.getUsername())) {
                    throw new BusinessException("登录密码不能为空");
                }
            } else {
                loginVO.setMobile(loginVO.getUsername());
                if (StringTzUtil.isBlankNull(loginVO.getMobile())) {
                    throw new BusinessException("手机号不能为空");
                }
                String regex = "^1[3-9]\\d{9}$";
                if (Pattern.matches(regex, loginVO.getMobile()) == false) {
                    throw new Exception("手机号格式不正确");
                }
            }

            SysUserEntity sysUserEntity;
            if (loginVO.getLogintype() == 0) {
                sysUserEntity = sysUserService.getUserByUserName(loginVO.getUsername());
                if (sysUserEntity == null || ObjectUtils.isEmpty(sysUserEntity.getId())) {
                    throw new BusinessException("该账号未注册");
                }
            } else {
                sysUserEntity = sysUserService.getUserByMobile(loginVO.getMobile());
                if (sysUserEntity == null || ObjectUtils.isEmpty(sysUserEntity.getId())) {
                    throw new BusinessException("该手机号未注册");
                }
                loginVO.setUsername(sysUserEntity.getUsername());
            }

            /*LoginUserBO loginUserBO = userService.login(loginVO.getUsername(), loginVO.getPassword(),
                    "codeKey", "code", loginVO.getLogintype(), loginVO.getMobile());*/
            LoginUserBO loginUserBO = authTokenService.login(loginVO.getUsername(), loginVO.getPassword()
                    , loginVO.getLogintype(), loginVO.getMobile());
            if (loginUserBO == null || StringUtils.isEmpty(loginUserBO.getToken())) {
                throw new BusinessException("登录失败");
            }

            checkReqSource(sysUserEntity.getOrgId());
/*
            List<SysRoleEntity> roles = sysUserService.listRoles4UserName(loginVO.getUsername());
            List<String> roleNames = new ArrayList<>();
            roles.forEach(item -> {
                roleNames.add(item.getName());
            });*/
            Collection<String> roleNames = authService.findUserRoleName4CacheAndDb(sysUserEntity.getId());
            List<SysMenuTreeDto> menuTreeDtos = authService.loadUserMenuTreeOnly(sysUserEntity.getId());

            Map<String, Object> userInfo = new HashMap<>();

            if (sysUserEntity != null) {
                userInfo.put("email", sysUserEntity.getEmail());
                userInfo.put("phone", sysUserEntity.getPhone());
                userInfo.put("nickname", sysUserEntity.getNickname());
                userInfo.put("status", sysUserEntity.getSysStatus());
                userInfo.put("userId", sysUserEntity.getId());
                userInfo.put("userName", sysUserEntity.getUsername());
                userInfo.put("orgId", sysUserEntity.getOrgId());
            }

            AjaxResultVO ajax = AjaxResultHelper.success();
            ajax.putData("token", loginUserBO.getToken());
            ajax.putData("roles", roleNames);
            ajax.putData("menuTree", menuTreeDtos);
            ajax.putData("userInfo", userInfo);
            log.info("login success:{}", loginVO.getUsername());

            //获取日志内容模板
            String logFormat = sysDictionaryService.getUniqueValue(ConstantConfig.LOGIN_LOG_DIC_NAME);
            String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            if (null != logFormat) {
                logFormat = logFormat.replaceAll("%userName%", loginVO.getUsername()).replaceAll("%loginTime%", date);
                // 组装记录登录日志
                SystemLogEntity systemLogEntity = new SystemLogEntity()
                        .setLogContent(logFormat)
                        .setLogType(SystemLogEntity.LogType.LOGIN_LOGOUT_LOG.getDescription())
                        .setModule(SystemLogEntity.Module.AUTH)
                        .setOperationTime(new Date())
                        .setOperator("system")
                        .setLogCategory(SystemLogEntity.LogType.LOGIN_LOGOUT_LOG.getCategory());
                systemLogService.save(systemLogEntity);
            }
            return ajax;
        } catch (BusinessException ex) {
            AjaxResultVO ajax = AjaxResultHelper.error();
            ajax.setCode(ex.getCode());
            ajax.setMsg(ex.getMessage());
            return ajax;
        } catch (Exception ex) {
            AjaxResultVO ajax = AjaxResultHelper.error();
            ajax.setCode("-1");
            ex.printStackTrace();
            ajax.setMsg(ex.getMessage());
            return ajax;
        }
    }

    /**
     * 检查请求来源，必须与当前登录的用户一样
     *
     * @param curUserOrgId
     */
    private void checkReqSource(Long curUserOrgId) {

        String loginSourceLimit = sysDictionaryService.getUniqueValue(ConstantConfig.loginSourceLimitKey);
        if (!StringTzUtil.isBlankNull(loginSourceLimit) && ConstantConfig.sys_off.equals(loginSourceLimit)) {
            log.info("系统配置，不校验登录来源限制，各厂在各地址登录");
            return;
        }

        String soruce = ServletUtil.getRequest().getHeader(AppConstant.source_header_name);
        if (StringUtils.isEmpty(soruce)) {
            soruce = "2";
        }
        if (!String.valueOf(curUserOrgId).equalsIgnoreCase(soruce)) {
            log.warn("用户ORG:{},loginSource:{}", curUserOrgId, soruce);
            throw new BusinessException(String.format("用户是（%s）厂的员工,请用（%s）厂的网址登录", curUserOrgId, curUserOrgId));
        }
    }

    @ApiOperation(value = "检查权限")
    @PostMapping("/checkAuth")
    public ResultBO checkAuth() {
        AjaxResultVO ajaxResultVO = AjaxResultHelper.success();
        return ajaxResultVO;
    }

    /*@ApiOperation(value = "登录", notes = "通过用户名密码登录，获取token,调用方必须把最新获取的token替换上一次的token,登录成功:code:0,data:token")
    @PostMapping("/login4ClientApp")
    public Result<String> login4ClientApp(@ApiParam("登录信息") @RequestBody LoginVO loginVO) {
        Result<String> result = new Result<>();
        try {
            String codeKey = "codeKey";
            if (StringUtils.isEmpty(appPwd)) {
                throw new BusinessException("请先在配置文件配置密码：appPwd");
            }
            if (appPwd.trim().equalsIgnoreCase(loginVO.getPassword())) {
                codeKey = "clientapp";
            }
           *//* LoginUserBO loginUserBO = userService.login(loginVO.getUsername(), loginVO.getPassword(),
                    codeKey, "code", loginVO.getLogintype(), loginVO.getMobile());*//*
            LoginUserBO loginUserBO = authTokenService.login(loginVO.getUsername(), loginVO.getPassword(),
                    loginVO.getLogintype(), loginVO.getMobile());
            result.setData(loginUserBO.getToken());
            result.setDescription("成功");
            result.setCode("0");
            return result;
        } catch (BusinessException ex) {
            result.setCode(ex.getCode());
            result.setDescription(ex.getMessage());
            return result;
        } catch (Exception ex) {
            result.setCode("-1");
            result.setDescription(ex.getMessage());
            return result;
        }
    }*/

    @GetMapping("/test")
    @GlobalApiResultJson
    public ResultBO test() {
        return AjaxResultHelper.success();
    }
}
